from flask import Blueprint, request, jsonify, current_app, g
from flasgger import swag_from
from datetime import datetime
import json
from sqlalchemy import or_
from app import db
from app.models import Activity, ActivityParticipant, User, Venue, Order
from app.utils.response import success_response, error_response
from app.utils.decorators import login_required
from app.utils.time_helper import safe_datetime_format, safe_date_format, safe_time_format

activity_bp = Blueprint('user_activity', __name__, url_prefix='/activities')

@activity_bp.route('/', methods=['GET'])
@swag_from({
    'tags': ['用户-活动'],
    'summary': '获取活动列表（小程序端）',
    'description': '用户查看活动列表，支持分页、搜索和筛选功能，无需登录即可查看。支持多种筛选条件：分页(page/perPage)、状态筛选(status)、关键词搜索(keyword)、场馆筛选(venue_id)、编号筛选(activity_ids，支持多个逗号分隔)、日期范围(start_date/end_date)。请求示例：GET /api/v1/user_api/activities/?page=1&perPage=10&status=open&keyword=篮球&activity_ids=1,2,3',
    'parameters': [
        {
            'name': 'page',
            'in': 'query',
            'type': 'integer',
            'default': 1,
            'description': '页码，从1开始'
        },
        {
            'name': 'perPage',
            'in': 'query',
            'type': 'integer',
            'default': 10,
            'description': '每页显示数量，建议10-50之间'
        },
        {
            'name': 'status',
            'in': 'query',
            'type': 'string',
            'description': '活动状态筛选：open(开放中)、closed(已关闭)、cancelled(已取消)'
        },
        {
            'name': 'venue_id',
            'in': 'query',
            'type': 'integer',
            'description': '场馆ID筛选，查看特定场馆的活动'
        },
        {
            'name': 'keyword',
            'in': 'query',
            'type': 'string',
            'description': '搜索关键词，可搜索活动标题和描述'
        },
        {
            'name': 'start_date',
            'in': 'query',
            'type': 'string',
            'description': '开始日期筛选，格式：YYYY-MM-DD'
        },
        {
            'name': 'end_date',
            'in': 'query',
            'type': 'string',
            'description': '结束日期筛选，格式：YYYY-MM-DD'
        },
        {
            'name': 'activity_ids',
            'in': 'query',
            'type': 'string',
            'description': '活动编号筛选，支持多个编号用逗号分隔，例如：1,2,3'
        },
        {
            'name': 'id',
            'in': 'query',
            'type': 'integer',
            'description': '活动ID筛选，等价于activity_ids=该id'
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'total': {'type': 'integer', 'description': '总记录数'},
                            'pages': {'type': 'integer', 'description': '总页数'},
                            'page': {'type': 'integer', 'description': '当前页码'},
                            'perPage': {'type': 'integer', 'description': '每页数量'},
                            'activities': {
                                'type': 'array',
                                'description': '活动列表',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'id': {'type': 'integer', 'description': '活动ID'},
                                        'title': {'type': 'string', 'description': '活动标题'},
                                        'description': {'type': 'string', 'description': '活动描述'},
                                        'organizer': {
                                            'type': 'object', 
                                            'description': '组织者信息',
                                            'properties': {
                                                'id': {'type': 'integer'},
                                                'nickname': {'type': 'string'},
                                                'avatar_url': {'type': 'string'}
                                            }
                                        },
                                        'venue_name': {'type': 'string', 'description': '场馆名称'},
                                        'start_time': {'type': 'string', 'description': '开始时间'},
                                        'end_time': {'type': 'string', 'description': '结束时间'},
                                        'max_participants': {'type': 'integer', 'description': '最大参与人数'},
                                        'participant_count': {'type': 'integer', 'description': '当前参与人数'},
                                        'status': {'type': 'string', 'description': '活动状态'},
                                        'is_free': {'type': 'boolean', 'description': '是否免费'},
                                        'fee': {'type': 'number', 'description': '活动费用'},
                                        'fee_description': {'type': 'string', 'description': '费用说明'},
                                        'images': {
                                            'type': 'array', 
                                            'description': '活动图片',
                                            'items': {'type': 'string'}
                                        },
                                        'created_at': {'type': 'string', 'description': '创建时间'},
                                        'can_join': {'type': 'boolean', 'description': '是否可以参与'},
                                        'participants': {
                                            'type': 'array',
                                            'description': '正式参与人列表',
                                            'items': {
                                                'type': 'object',
                                                'properties': {
                                                    'id': {'type': 'integer', 'description': '用户ID'},
                                                    'nickname': {'type': 'string', 'description': '用户昵称'},
                                                    'avatar_url': {'type': 'string', 'description': '用户头像'},
                                                    'joined_at': {'type': 'string', 'description': '参与时间'}
                                                }
                                            }
                                        },
                                        'waitlist_participants': {
                                            'type': 'array',
                                            'description': '候补用户列表',
                                            'items': {
                                                'type': 'object',
                                                'properties': {
                                                    'id': {'type': 'integer', 'description': '用户ID'},
                                                    'nickname': {'type': 'string', 'description': '用户昵称'},
                                                    'avatar_url': {'type': 'string', 'description': '用户头像'},
                                                    'joined_at': {'type': 'string', 'description': '加入候补时间'},
                                                    'waitlist_position': {'type': 'integer', 'description': '候补排队位置'}
                                                }
                                            }
                                        },
                                        'waitlist_count': {'type': 'integer', 'description': '候补总人数'},
                                        'current_user_status': {'type': 'string', 'description': '当前用户状态', 'enum': ['joined', 'waitlist', 'not_joined', 'pending', 'left']}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
})
@login_required
def get_activities():
    """获取活动列表"""
    try:
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 50)
        status = request.args.get('status')
        keyword = request.args.get('keyword')
        venue_id = request.args.get('venue_id', type=int)
        activity_ids = request.args.get('activity_ids')
        
        # 处理id参数，确保是有效的整数
        activity_id = None
        try:
            activity_id = request.args.get('id', type=int)
        except (ValueError, TypeError):
            # 如果id参数不是有效整数，忽略该参数
            pass
        
        # 构建查询 - 只显示活跃的活动
        query = Activity.query.filter_by(is_active=True)
        
        # 过滤私人活动 - 不显示任何一键预定的活动
        query = query.filter(Activity.activity_type != 'quick_booking')
        
        # 状态筛选
        if status:
            query = query.filter_by(status=status)
        
        # 关键词搜索
        if keyword:
            query = query.filter(or_(
                Activity.title.like(f'%{keyword}%'),
                Activity.description.like(f'%{keyword}%')
            ))
        
        # 场馆筛选
        if venue_id:
            query = query.filter_by(venue_id=venue_id)
        
        # id参数支持，等价于activity_ids
        if activity_id:
            activity_ids = str(activity_id) if not activity_ids else f"{activity_ids},{activity_id}"
        
        # 活动编号筛选
        if activity_ids:
            try:
                # 解析逗号分隔的ID字符串
                id_list = [int(id.strip()) for id in activity_ids.split(',') if id.strip().isdigit()]
                if id_list:
                    query = query.filter(Activity.id.in_(id_list))
            except ValueError:
                # 如果解析失败，忽略该筛选条件
                pass
        
        # 分页查询
        pagination = query.order_by(Activity.created_at.desc()).paginate(
            page=page, per_page=per_page, error_out=False
        )
        
        activities = []
        for activity in pagination.items:
            activity_data = activity.to_dict(include_venue=True, include_organizer=True, include_participants=True)
            
            # 检查当前用户的参与状态
            current_participant = ActivityParticipant.query.filter_by(
                activity_id=activity.id,
                user_id=g.current_user_id
            ).first()
            
            # 检查当前用户是否为活动发起人
            is_organizer = activity.organizer_id == int(g.current_user_id)
            
            # 添加当前用户状态
            current_user_status = 'not_joined'
            if current_participant:
                current_user_status = current_participant.status
            activity_data['current_user_status'] = current_user_status
            
            # 添加是否可加入标识
            can_join = False
            if activity.status == 'open' and current_user_status == 'not_joined' and not is_organizer:
                if activity.current_participants < activity.max_participants:
                    can_join = True  # 可以直接加入
                elif activity.allow_waitlist:
                    can_join = True  # 可以加入候补
            
            activity_data['can_join'] = can_join
            
            # 确保价格字段存在
            activity_data['is_free'] = activity.is_free
            activity_data['fee'] = float(activity.fee) if activity.fee else 0.0
            activity_data['fee_description'] = activity.fee_description
            activities.append(activity_data)
        
        return success_response({
            'activities': activities,
            'total': pagination.total,
            'page': page,
            'pages': pagination.pages,
            'per_page': per_page
        }, '获取成功')
        
    except Exception as e:
        current_app.logger.error(f"获取活动列表失败: {str(e)}")
        return error_response('获取失败', 500)

@activity_bp.route('/<int:activity_id>', methods=['GET'])
@swag_from({
    'tags': ['用户-活动'],
    'summary': '获取活动详情（小程序端）',
    'description': '用户查看活动详细信息，包含参与者列表，需要在请求头中包含JWT token进行用户认证。返回内容包括活动基本信息（标题、描述、时间等）、组织者信息、场馆信息、参与者列表、活动状态和设置。请求示例：GET /api/v1/user_api/activities/123',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '活动ID'
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'id': {'type': 'integer'},
                            'title': {'type': 'string'},
                            'description': {'type': 'string'},
                            'organizer': {
                                'type': 'object',
                                'properties': {
                                    'id': {'type': 'integer'},
                                    'nickname': {'type': 'string'},
                                    'avatar_url': {'type': 'string'}
                                }
                            },
                            'venue': {
                                'type': 'object',
                                'properties': {
                                    'id': {'type': 'integer'},
                                    'name': {'type': 'string'},
                                    'location': {'type': 'string'}
                                }
                            },
                            'start_time': {'type': 'string'},
                            'end_time': {'type': 'string'},
                            'max_participants': {'type': 'integer'},
                            'participant_count': {'type': 'integer'},
                            'participants': {
                                'type': 'array',
                                'description': '正式参与者列表',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'id': {'type': 'integer'},
                                        'nickname': {'type': 'string'},
                                        'avatar_url': {'type': 'string'},
                                        'joined_at': {'type': 'string', 'description': '加入时间'}
                                    }
                                }
                            },
                            'waitlist_participants': {
                                'type': 'array',
                                'description': '候补用户列表',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'id': {'type': 'integer'},
                                        'nickname': {'type': 'string'},
                                        'avatar_url': {'type': 'string'},
                                        'joined_at': {'type': 'string', 'description': '加入候补时间'},
                                        'waitlist_position': {'type': 'integer', 'description': '候补排队位置'}
                                    }
                                }
                            },
                            'waitlist_count': {'type': 'integer', 'description': '候补总人数'},
                            'current_user_status': {'type': 'string', 'description': '当前用户状态', 'enum': ['joined', 'waitlist', 'not_joined', 'pending', 'left']},
                            'current_user_waitlist_position': {'type': 'integer', 'description': '当前用户候补排队位置（仅当状态为waitlist时返回）'},
                            'status': {'type': 'string'},
                            'images': {
                                'type': 'array',
                                'items': {'type': 'string'}
                            },
                            'is_participant': {'type': 'boolean'},
                            'can_join': {'type': 'boolean'}
                        }
                    }
                }
            }
        },
        401: {
            'description': 'token验证失败，需要重新登录'
        },
        404: {
            'description': '活动不存在'
        }
    }
})
@login_required
def get_activity_detail(activity_id):
    """获取活动详情"""
    try:
        activity = Activity.query.get(activity_id)
        if not activity or not activity.is_active:
            return error_response('活动不存在', 404)
        
        # 检查私人活动权限 - 只有创建者能查看私人活动
        current_user_id = int(g.current_user_id)
        if (activity.notes and '此活动为一键预定生成的私人活动' in activity.notes and 
            activity.organizer_id != current_user_id):
            return error_response('活动不存在', 404)
        
        # 增加浏览次数
        activity.view_count = (activity.view_count or 0) + 1
        db.session.commit()
        
        # 获取活动详情，包含组织者、参与者和场馆信息
        activity_data = activity.to_dict(
            include_organizer=True,
            include_participants=True,
            include_venue=True
        )
        
        # 检查当前用户参与状态
        current_participant = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            user_id=g.current_user_id
        ).first()
        
        current_user_status = 'not_joined'
        if current_participant:
            current_user_status = current_participant.status
        
        activity_data['current_user_status'] = current_user_status
        activity_data['is_participant'] = current_user_status == 'joined'
        
        # 判断是否可以加入
        can_join = False
        if activity.status == 'open' and current_user_status == 'not_joined':
            if activity.current_participants < activity.max_participants:
                can_join = True
            elif activity.allow_waitlist:
                can_join = True  # 可以加入候补
        
        activity_data['can_join'] = can_join
        
        # 添加候补相关信息
        waitlist_count = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='waitlist'
        ).count()
        
        activity_data['waitlist_count'] = waitlist_count
        
        # 如果当前用户在候补名单中，计算排队位置
        if current_user_status == 'waitlist':
            waitlist_position = ActivityParticipant.query.filter_by(
                activity_id=activity_id,
                status='waitlist'
            ).filter(ActivityParticipant.created_at <= current_participant.created_at).count()
            activity_data['current_user_waitlist_position'] = waitlist_position
        
        return success_response(activity_data, '获取成功')
        
    except Exception as e:
        current_app.logger.error(f"获取活动详情失败: {str(e)}")
        return error_response('获取失败', 500)

@activity_bp.route('/<int:activity_id>/join', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '参与活动（小程序端）',
    'description': '用户报名参加活动，支持候补功能。需要在请求头中包含JWT token进行用户认证。业务逻辑：检查活动是否存在且开放、检查用户是否已参与、检查活动人数限制。如果活动已满且允许候补，用户将加入候补名单；否则直接参与活动。请求示例：POST /api/v1/user_api/activities/123/join，Headers: Authorization: Bearer your_jwt_token',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '活动ID'
        }
    ],
    'responses': {
        200: {
            'description': '参与成功或加入候补',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '报名成功 or 已加入候补名单'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'activity_id': {'type': 'integer', 'description': '活动ID'},
                            'participant_id': {'type': 'integer', 'description': '参与记录ID'},
                            'status': {'type': 'string', 'description': '参与状态：joined=已参与, waitlist=候补中', 'enum': ['joined', 'waitlist']},
                            'join_time': {'type': 'string', 'description': '报名时间'},
                            'participant_count': {'type': 'integer', 'description': '当前参与人数（不包括候补）'},
                            'max_participants': {'type': 'integer', 'description': '最大参与人数'},
                            'waitlist_position': {'type': 'integer', 'description': '候补排队位置（仅当status为waitlist时返回）'}
                        }
                    }
                }
            }
        },
        400: {
            'description': '活动已满且不允许候补，或其他业务错误'
        },
        401: {
            'description': 'token验证失败，需要重新登录'
        },
        403: {
            'description': '活动不开放报名'
        },
        404: {
            'description': '活动不存在'
        }
    }
})
def join_activity(activity_id):
    """参与活动"""
    try:
        activity = Activity.query.get(activity_id)
        if not activity or not activity.is_active:
            return error_response('活动不存在', 404)
        
        # 检查活动状态
        if activity.status != 'open':
            return error_response('活动当前不开放报名', 403)
        
        # 检查是否已经参与
        existing_participant = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            user_id=g.current_user_id
        ).first()
        
        if existing_participant:
            if existing_participant.status == 'joined':
                return error_response('您已经参与了这个活动', 400)
            elif existing_participant.status == 'pending':
                return error_response('您的报名正在审核中', 400)
            elif existing_participant.status == 'waitlist':
                return error_response('您已在候补名单中', 400)
            elif existing_participant.status == 'left':
                # 用户之前退出过，现在重新加入
                # 需要检查是否还有位置或需要进入候补
                if activity.current_participants >= activity.max_participants:
                    # 活动已满，检查是否允许候补
                    if activity.allow_waitlist:
                        existing_participant.status = 'waitlist'
                        from datetime import datetime
                        existing_participant.joined_at = datetime.now()
                        participant = existing_participant
                    else:
                        return error_response('活动人数已满且不允许候补', 400)
                else:
                    # 还有位置，直接加入
                    existing_participant.status = 'joined'
                    from datetime import datetime
                    existing_participant.joined_at = datetime.now()
                    participant = existing_participant
            else:
                return error_response('参与状态异常', 400)
        else:
            # 创建新的参与记录
            # 检查人数限制
            if activity.current_participants >= activity.max_participants:
                # 活动已满，检查是否允许候补
                if activity.allow_waitlist:
                    participant = ActivityParticipant(
                        activity_id=activity_id,
                        user_id=g.current_user_id,
                        status='waitlist'  # 进入候补名单
                    )
                    db.session.add(participant)
                else:
                    return error_response('活动人数已满且不允许候补', 400)
            else:
                # 还有位置，直接加入
                participant = ActivityParticipant(
                    activity_id=activity_id,
                    user_id=g.current_user_id,
                    status='joined'  # 直接加入
                )
                db.session.add(participant)
        
        db.session.flush()  # 确保participant被写入，以便计算正确的count
        
        # 更新活动参与人数（只计算joined状态的用户）
        activity.current_participants = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='joined'
        ).count()
        
        db.session.commit()
        
        # 根据参与状态返回不同的响应消息
        if participant.status == 'joined':
            message = '报名成功'
            response_data = {
                'activity_id': activity_id,
                'participant_id': participant.id,
                'status': 'joined',
                'join_time': participant.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'participant_count': activity.current_participants,
                'max_participants': activity.max_participants
            }
        elif participant.status == 'waitlist':
            # 计算候补排序位置
            waitlist_position = ActivityParticipant.query.filter_by(
                activity_id=activity_id,
                status='waitlist'
            ).filter(ActivityParticipant.created_at <= participant.created_at).count()
            
            message = '已加入候补名单'
            response_data = {
                'activity_id': activity_id,
                'participant_id': participant.id,
                'status': 'waitlist',
                'join_time': participant.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                'waitlist_position': waitlist_position,
                'participant_count': activity.current_participants,
                'max_participants': activity.max_participants
            }
        else:
            message = '报名成功'
            response_data = {
                'activity_id': activity_id,
                'participant_id': participant.id,
                'status': participant.status,
                'join_time': participant.created_at.strftime('%Y-%m-%d %H:%M:%S')
            }
        
        return success_response(response_data, message)
        
    except Exception as e:
        current_app.logger.error(f"参与活动失败: {str(e)}")
        db.session.rollback()
        return error_response('报名失败', 500)

@activity_bp.route('/<int:activity_id>/leave', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '退出活动（小程序端）',
    'description': '用户退出已参与的活动，支持候补自动提升功能。需要在请求头中包含JWT token进行用户认证。业务逻辑：检查活动是否存在、检查用户是否已参与该活动、检查是否允许退出（活动状态等）、更新参与状态并减少参与人数。如果有候补用户，将自动提升最早的候补用户为正式参与者。请求示例：POST /api/v1/user_api/activities/123/leave，Headers: Authorization: Bearer your_jwt_token',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '活动ID'
        }
    ],
    'responses': {
        200: {
            'description': '退出成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '退出成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'activity_id': {'type': 'integer'},
                            'participant_count': {'type': 'integer', 'description': '当前参与人数'},
                            'left_at': {'type': 'string', 'description': '退出时间'},
                            'promoted_user': {
                                'type': 'object',
                                'description': '被提升的候补用户信息（如果有）',
                                'properties': {
                                    'id': {'type': 'integer'},
                                    'nickname': {'type': 'string'},
                                    'avatar_url': {'type': 'string'}
                                }
                            }
                        }
                    }
                }
            }
        },
        400: {
            'description': '活动已开始无法退出等错误'
        },
        401: {
            'description': 'token验证失败，需要重新登录'
        },
        404: {
            'description': '活动不存在或用户未参与该活动'
        }
    }
})
def leave_activity(activity_id):
    """退出活动"""
    try:
        activity = Activity.query.get(activity_id)
        if not activity or not activity.is_active:
            return error_response('活动不存在', 404)
        
        # 查找参与记录
        participant = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            user_id=g.current_user_id,
            status='joined'
        ).first()
        
        if not participant:
            return error_response('您还没有参与这个活动', 400)
        
        # 检查是否可以退出（活动开始前可以退出）
        from datetime import datetime
        if activity.start_time and activity.start_time <= datetime.now():
            return error_response('活动已开始，无法退出', 400)
        
        # 更新参与状态为已退出
        participant.status = 'left'
        db.session.flush()  # 确保状态更新被写入
        
        # 更新活动参与人数
        activity.current_participants = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='joined'
        ).count()
        
        # 检查是否有候补用户需要自动加入
        promoted_user = None
        if activity.allow_waitlist:
            # 查找最早的候补用户
            waitlist_participant = ActivityParticipant.query.filter_by(
                activity_id=activity_id,
                status='waitlist'
            ).order_by(ActivityParticipant.created_at.asc()).first()
            
            if waitlist_participant:
                # 将候补用户提升为正式参与者
                waitlist_participant.status = 'joined'
                from datetime import datetime
                waitlist_participant.joined_at = datetime.now()
                
                # 重新计算参与人数
                activity.current_participants = ActivityParticipant.query.filter_by(
                    activity_id=activity_id,
                    status='joined'
                ).count()
                
                # 获取被提升用户的信息用于响应
                if waitlist_participant.user:
                    promoted_user = {
                        'id': waitlist_participant.user.id,
                        'nickname': waitlist_participant.user.nickname,
                        'avatar_url': waitlist_participant.user.avatar_url
                    }
        
        db.session.commit()
        
        response_data = {
            'activity_id': activity_id,
            'participant_count': activity.current_participants,
            'left_at': safe_datetime_format(datetime.now())
        }
        
        message = '退出成功'
        if promoted_user:
            response_data['promoted_user'] = promoted_user
            message = '退出成功，候补用户已自动加入'
        
        return success_response(response_data, message)
        
    except Exception as e:
        current_app.logger.error(f"退出活动失败: {str(e)}")
        db.session.rollback()
        return error_response('退出失败', 500)

@activity_bp.route('/<int:activity_id>/waitlist', methods=['GET'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '获取活动候补名单（小程序端）',
    'description': '获取指定活动的候补名单信息，包括候补用户列表和当前用户的候补状态。需要在请求头中包含JWT token进行用户认证。',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '活动ID'
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'activity_id': {'type': 'integer'},
                            'allow_waitlist': {'type': 'boolean', 'description': '是否允许候补'},
                            'waitlist_count': {'type': 'integer', 'description': '候补总人数'},
                            'current_user_status': {'type': 'string', 'description': '当前用户状态', 'enum': ['joined', 'waitlist', 'not_joined']},
                            'current_user_position': {'type': 'integer', 'description': '当前用户候补排队位置（仅当状态为waitlist时返回）'},
                            'waitlist_users': {
                                'type': 'array',
                                'description': '候补用户列表（仅显示前10位）',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'id': {'type': 'integer'},
                                        'nickname': {'type': 'string'},
                                        'avatar_url': {'type': 'string'},
                                        'waitlist_time': {'type': 'string'},
                                        'position': {'type': 'integer'}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        401: {
            'description': 'token验证失败，需要重新登录'
        },
        404: {
            'description': '活动不存在'
        }
    }
})
def get_activity_waitlist(activity_id):
    """获取活动候补名单"""
    try:
        activity = Activity.query.get(activity_id)
        if not activity or not activity.is_active:
            return error_response('活动不存在', 404)
        
        # 获取所有候补用户
        waitlist_participants = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='waitlist'
        ).order_by(ActivityParticipant.created_at.asc()).all()
        
        # 检查当前用户状态
        current_user_participant = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            user_id=g.current_user_id
        ).first()
        
        current_user_status = 'not_joined'
        current_user_position = None
        
        if current_user_participant:
            current_user_status = current_user_participant.status
            if current_user_status == 'waitlist':
                # 计算当前用户的候补位置
                current_user_position = ActivityParticipant.query.filter_by(
                    activity_id=activity_id,
                    status='waitlist'
                ).filter(ActivityParticipant.created_at <= current_user_participant.created_at).count()
        
        # 构建候补用户列表（只显示前10位）
        waitlist_users = []
        for index, participant in enumerate(waitlist_participants[:10], 1):
            if participant.user:
                waitlist_users.append({
                    'id': participant.user.id,
                    'nickname': participant.user.nickname,
                    'avatar_url': participant.user.avatar_url,
                    'waitlist_time': safe_datetime_format(participant.created_at),
                    'position': index
                })
        
        response_data = {
            'activity_id': activity_id,
            'allow_waitlist': activity.allow_waitlist,
            'waitlist_count': len(waitlist_participants),
            'current_user_status': current_user_status,
            'waitlist_users': waitlist_users
        }
        
        if current_user_position is not None:
            response_data['current_user_position'] = current_user_position
        
        return success_response(response_data, '获取成功')
        
    except Exception as e:
        current_app.logger.error(f"获取候补名单失败: {str(e)}")
        return error_response('获取失败', 500)

@activity_bp.route('/my', methods=['GET'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '我的活动列表（小程序端）',
    'description': '获取当前用户的活动列表，可筛选发起的活动或参与的活动。需要在请求头中包含JWT token进行用户认证。支持分页和状态筛选。请求示例：GET /api/v1/user_api/activities/my?page=1&perPage=10&status=open&role=organizer，Headers: Authorization: Bearer your_jwt_token',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'page',
            'in': 'query',
            'type': 'integer',
            'default': 1,
            'description': '页码（仅对参与的活动有效）'
        },
        {
            'name': 'perPage',
            'in': 'query',
            'type': 'integer',
            'default': 10,
            'description': '每页数量（仅对参与的活动有效）'
        },
        {
            'name': 'status',
            'in': 'query',
            'type': 'string',
            'description': '活动状态筛选：open(开放中)、closed(已关闭)、cancelled(已取消)、completed(已完成)'
        },
        {
            'name': 'role',
            'in': 'query',
            'type': 'string',
            'description': '角色筛选：organizer(我发起的)、participant(我参与的)，默认返回全部',
            'enum': ['organizer', 'participant']
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'organized_activities': {
                                'type': 'object',
                                'description': '我发起的活动',
                                'properties': {
                                    'total': {'type': 'integer', 'description': '发起活动总数'},
                                    'activities': {
                                        'type': 'array',
                                        'description': '发起的活动列表',
                                        'items': {
                                            'type': 'object',
                                            'properties': {
                                                'id': {'type': 'integer'},
                                                'title': {'type': 'string'},
                                                'description': {'type': 'string'},
                                                'start_time': {'type': 'string'},
                                                'end_time': {'type': 'string'},
                                                'status': {'type': 'string'},
                                                'participant_count': {'type': 'integer'},
                                                'max_participants': {'type': 'integer'},
                                                'venue_name': {'type': 'string'},
                                                'created_at': {'type': 'string'},
                                                'is_free': {'type': 'boolean', 'description': '是否免费'},
                                                'fee': {'type': 'number', 'description': '活动费用'},
                                                'fee_description': {'type': 'string', 'description': '费用说明'}
                                            }
                                        }
                                    }
                                }
                            },
                            'participated_activities': {
                                'type': 'object',
                                'description': '我参与的活动',
                                'properties': {
                                    'total': {'type': 'integer', 'description': '参与活动总数'},
                                    'pages': {'type': 'integer', 'description': '总页数'},
                                    'page': {'type': 'integer', 'description': '当前页码'},
                                    'perPage': {'type': 'integer', 'description': '每页数量'},
                                    'activities': {
                                        'type': 'array',
                                        'description': '参与的活动列表',
                                        'items': {
                                            'type': 'object',
                                            'properties': {
                                                'activity': {
                                                    'type': 'object', 
                                                    'description': '活动信息',
                                                    'properties': {
                                                        'id': {'type': 'integer'},
                                                        'title': {'type': 'string'},
                                                        'description': {'type': 'string'},
                                                        'start_time': {'type': 'string'},
                                                        'end_time': {'type': 'string'},
                                                        'status': {'type': 'string'},
                                                        'organizer': {
                                                            'type': 'object',
                                                            'properties': {
                                                                'id': {'type': 'integer'},
                                                                'nickname': {'type': 'string'},
                                                                'avatar_url': {'type': 'string'}
                                                            }
                                                        },
                                                        'venue_name': {'type': 'string'},
                                                        'is_free': {'type': 'boolean', 'description': '是否免费'},
                                                        'fee': {'type': 'number', 'description': '活动费用'},
                                                        'fee_description': {'type': 'string', 'description': '费用说明'}
                                                    }
                                                },
                                                'participation': {
                                                    'type': 'object',
                                                    'description': '参与信息',
                                                    'properties': {
                                                        'status': {'type': 'string', 'description': '参与状态'},
                                                        'join_time': {'type': 'string', 'description': '参与时间'}
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        401: {
            'description': 'token验证失败，需要重新登录'
        }
    }
})
def get_my_activities():
    """获取我的活动列表"""
    try:
        # 获取当前用户信息
        current_user = User.query.get(int(g.current_user_id))
        if not current_user:
            return error_response('用户不存在', 404)
        
        page = request.args.get('page', 1, type=int)
        per_page = min(request.args.get('per_page', 10, type=int), 50)
        status = request.args.get('status')
        role = request.args.get('role')  # 角色筛选：organizer, participant
        
        from datetime import datetime
        current_time = datetime.now()
        
        # 根据role参数决定获取哪些活动
        organized_list = []
        participated_list = []
        
        # 1. 获取我发起的活动（当role为空或为organizer时）
        if not role or role == 'organizer':
            organized_query = Activity.query.filter_by(
                organizer_id=int(g.current_user_id),
                is_active=True
            )
            
            # 处理状态筛选
            if status:
                if status == 'completed':
                    # 已完成：活动时间已过且状态为closed
                    organized_query = organized_query.filter(
                        Activity.status == 'closed',
                        Activity.end_time < current_time
                    )
                elif status == 'closed':
                    # 已关闭：活动时间未到但状态为closed
                    organized_query = organized_query.filter(
                        Activity.status == 'closed',
                        Activity.end_time >= current_time
                    )
                else:
                    # 其他状态：open, cancelled
                    organized_query = organized_query.filter_by(status=status)
            
            organized_activities = organized_query.order_by(Activity.created_at.desc()).all()
            
            for activity in organized_activities:
                # 计算实际显示状态
                display_status = activity.status
                if activity.status == 'closed':
                    if activity.end_time < current_time:
                        display_status = 'completed'
                    else:
                        display_status = 'closed'
                
                # 解析活动图片
                try:
                    images = json.loads(activity.images) if activity.images else []
                except (json.JSONDecodeError, TypeError):
                    images = []
                
                # 构建场馆信息
                venue_info = None
                if activity.venue:
                    venue_info = {
                        'id': activity.venue.id,
                        'name': activity.venue.name,
                        'type': activity.venue.type,
                        'address': activity.venue.address,
                        'location': activity.venue.location,
                        'latitude': activity.venue.latitude,
                        'longitude': activity.venue.longitude
                    }
                
                # 获取参与者信息
                participants_list = []
                joined_participants = activity.participants.filter_by(status='joined').all()
                for participant in joined_participants:
                    if participant.user:
                        participants_list.append({
                            'id': participant.user.id,
                            'nickname': participant.user.nickname,
                            'avatar_url': participant.user.avatar_url,
                            'joined_at': safe_datetime_format(participant.joined_at),
                            'status': participant.status
                        })
                
                organized_list.append({
                    'id': activity.id,
                    'title': activity.title,
                    'description': activity.description,
                    'start_time': safe_datetime_format(activity.start_time),
                    'end_time': safe_datetime_format(activity.end_time),
                    'status': display_status,
                    'participant_count': activity.current_participants,
                    'max_participants': activity.max_participants,
                    'venue_name': activity.venue.name if activity.venue else (activity.location_name or '未指定场馆'),
                    'venue': venue_info,  # 添加完整场馆信息
                    'organizer': {  # 添加发起人（当前用户）信息
                        'id': current_user.id,
                        'nickname': current_user.nickname,
                        'avatar_url': current_user.avatar_url
                    },
                    'participants': participants_list,  # 添加参与者列表
                    'created_at': safe_datetime_format(activity.created_at),
                    'role': 'organizer',  # 标识用户在此活动中的角色
                    'is_free': activity.is_free,
                    'fee': float(activity.fee) if activity.fee else 0.0,
                    'fee_description': activity.fee_description,
                    'view_count': activity.view_count or 0,  # 添加浏览次数
                    'images': images  # 添加活动图片
                })
        
        # 2. 获取我参与的活动（当role为空或为participant时）
        pagination = None
        if not role or role == 'participant':
            # 获取我参与的活动（包括我发起并自己参与的）
            participated_query = ActivityParticipant.query.filter_by(user_id=int(g.current_user_id))
            
            # 获取我发起的活动ID列表，用于合并和去重
            organized_activity_ids = [activity['id'] for activity in organized_list] if organized_list else []
            
            # 先收集所有参与活动（包括发起的活动）
            all_participated_activities = []
            
            # 1. 添加我发起的活动到参与列表（作为发起者参与）
            for organized_activity in organized_list:
                activity = Activity.query.get(organized_activity['id'])
                if activity and activity.is_active:
                    # 计算实际显示状态
                    display_status = activity.status
                    if activity.status == 'closed':
                        if activity.end_time < current_time:
                            display_status = 'completed'
                        else:
                            display_status = 'closed'
                    
                    # 如果指定了状态筛选，需要检查活动状态
                    if status:
                        if status == 'completed':
                            if display_status != 'completed':
                                continue
                        elif status == 'closed':
                            if display_status != 'closed':
                                continue
                        else:
                            if display_status != status:
                                continue
                    
                    # 解析活动图片
                    try:
                        images = json.loads(activity.images) if activity.images else []
                    except (json.JSONDecodeError, TypeError):
                        images = []
                    
                    # 构建场馆信息
                    venue_info = None
                    if activity.venue:
                        venue_info = {
                            'id': activity.venue.id,
                            'name': activity.venue.name,
                            'type': activity.venue.type,
                            'address': activity.venue.address,
                            'location': activity.venue.location,
                            'latitude': activity.venue.latitude,
                            'longitude': activity.venue.longitude
                        }
                    
                    # 获取参与者信息
                    participants_list = []
                    joined_participants = activity.participants.filter_by(status='joined').all()
                    for participant in joined_participants:
                        if participant.user:
                            participants_list.append({
                                'id': participant.user.id,
                                'nickname': participant.user.nickname,
                                'avatar_url': participant.user.avatar_url,
                                'joined_at': safe_datetime_format(participant.joined_at),
                                'status': participant.status
                            })
                    
                    all_participated_activities.append({
                        'activity': {
                            'id': activity.id,
                            'title': activity.title,
                            'description': activity.description,
                            'start_time': safe_datetime_format(activity.start_time),
                            'end_time': safe_datetime_format(activity.end_time),
                            'status': display_status,
                            'organizer': {
                                'id': current_user.id,
                                'nickname': current_user.nickname,
                                'avatar_url': current_user.avatar_url
                            },
                            'venue_name': activity.venue.name if activity.venue else (activity.location_name or '未指定场馆'),
                            'venue': venue_info,  # 添加完整场馆信息
                            'participant_count': activity.current_participants,
                            'max_participants': activity.max_participants,
                            'is_free': activity.is_free,
                            'fee': float(activity.fee) if activity.fee else 0.0,
                            'fee_description': activity.fee_description,
                            'view_count': activity.view_count or 0,  # 添加浏览次数
                            'images': images,  # 添加活动图片
                            'participants': participants_list  # 添加参与者列表
                        },
                        'participation': {
                            'status': 'joined',
                            'join_time': safe_datetime_format(activity.created_at),  # 使用活动创建时间作为参与时间
                            'role': 'organizer'  # 标识用户在此活动中的角色是发起者
                        },
                        'created_at': activity.created_at  # 用于排序
                    })
            
            # 2. 添加我纯参与的活动（排除已经作为发起者添加的）
            participated_query_items = participated_query.order_by(ActivityParticipant.created_at.desc()).all()
            
            for participant in participated_query_items:
                # 跳过我发起的活动（已经添加过了）
                if participant.activity_id in organized_activity_ids:
                    continue
                    
                activity = Activity.query.get(participant.activity_id)
                if activity and activity.is_active:
                    # 增加筛选，如果是我参与的活动，也排除一键预定的私人活动
                    if activity.notes and '此活动为一键预定生成的私人活动' in activity.notes:
                        continue

                    # 计算实际显示状态
                    display_status = activity.status
                    if activity.status == 'closed':
                        if activity.end_time < current_time:
                            display_status = 'completed'
                        else:
                            display_status = 'closed'
                    
                    # 如果指定了状态筛选，需要检查活动状态
                    if status:
                        if status == 'completed':
                            if display_status != 'completed':
                                continue
                        elif status == 'closed':
                            if display_status != 'closed':
                                continue
                        else:
                            if display_status != status:
                                continue
                        
                    # 解析活动图片
                    try:
                        images = json.loads(activity.images) if activity.images else []
                    except (json.JSONDecodeError, TypeError):
                        images = []
                    
                    # 构建场馆信息
                    venue_info = None
                    if activity.venue:
                        venue_info = {
                            'id': activity.venue.id,
                            'name': activity.venue.name,
                            'type': activity.venue.type,
                            'address': activity.venue.address,
                            'location': activity.venue.location,
                            'latitude': activity.venue.latitude,
                            'longitude': activity.venue.longitude
                        }
                    
                    # 获取参与者信息
                    participants_list = []
                    joined_participants = activity.participants.filter_by(status='joined').all()
                    for participant in joined_participants:
                        if participant.user:
                            participants_list.append({
                                'id': participant.user.id,
                                'nickname': participant.user.nickname,
                                'avatar_url': participant.user.avatar_url,
                                'joined_at': safe_datetime_format(participant.joined_at),
                                'status': participant.status
                            })
                    
                    all_participated_activities.append({
                        'activity': {
                            'id': activity.id,
                            'title': activity.title,
                            'description': activity.description,
                            'start_time': safe_datetime_format(activity.start_time),
                            'end_time': safe_datetime_format(activity.end_time),
                            'status': display_status,
                            'organizer': {
                                'id': activity.organizer.id,
                                'nickname': activity.organizer.nickname,
                                'avatar_url': activity.organizer.avatar_url
                            } if activity.organizer else None,
                            'venue_name': activity.venue.name if activity.venue else (activity.location_name or '未指定场馆'),
                            'venue': venue_info,  # 添加完整场馆信息
                            'participant_count': activity.current_participants,
                            'max_participants': activity.max_participants,
                            'is_free': activity.is_free,
                            'fee': float(activity.fee) if activity.fee else 0.0,
                            'fee_description': activity.fee_description,
                            'view_count': activity.view_count or 0,  # 添加浏览次数
                            'images': images,  # 添加活动图片
                            'participants': participants_list  # 添加参与者列表
                        },
                        'participation': {
                            'status': participant.status,
                            'join_time': safe_datetime_format(participant.created_at),
                            'role': 'participant'  # 标识用户在此活动中的角色
                        },
                        'created_at': participant.created_at  # 用于排序
                    })
            
            # 3. 按时间排序（最新的在前面）
            all_participated_activities.sort(key=lambda x: x['created_at'], reverse=True)
            
            # 4. 手动分页
            total_count = len(all_participated_activities)
            start_index = (page - 1) * per_page
            end_index = start_index + per_page
            participated_list = [item for item in all_participated_activities[start_index:end_index]]
            
            # 移除临时的排序字段
            for item in participated_list:
                item.pop('created_at', None)
            
            # 5. 创建分页信息
            pagination = type('Pagination', (), {
                'total': total_count,
                'pages': (total_count + per_page - 1) // per_page,  # 向上取整
                'page': page,
                'per_page': per_page
            })()
        
        # 构建返回数据
        response_data = {
            'organized_activities': {
                'total': len(organized_list),
                'activities': organized_list
            },
            'participated_activities': {
                'total': pagination.total if pagination else 0,
                'pages': pagination.pages if pagination else 0,
                'page': page,
                'perPage': per_page,
                'activities': participated_list
            }
        }
        
        return success_response(response_data, '获取成功')
        
    except Exception as e:
        current_app.logger.error(f"获取我的活动失败: {str(e)}")
        return error_response('获取失败', 500)

@activity_bp.route('/create', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '创建活动（小程序端）',
    'description': '用户创建新活动，需要在请求头中包含JWT token进行用户认证。当前用户自动成为活动组织者。支持设置活动基本信息、时间、地点、参与人数限制等。请求示例：POST /api/v1/user_api/activities/create，Headers: Authorization: Bearer your_jwt_token',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}，从登录接口获取'
        },
        {
            'name': 'body',
            'in': 'body',
            'required': True,
            'schema': {
                'type': 'object',
                'required': ['title', 'start_time', 'end_time'],
                'properties': {
                    'title': {'type': 'string', 'description': '活动标题', 'example': '周末篮球友谊赛'},
                    'description': {'type': 'string', 'description': '活动描述', 'example': '欢迎大家参与周末篮球友谊赛，锻炼身体，结交朋友！'},
                    'venue_id': {'type': 'integer', 'description': '场馆ID（可选）', 'example': 1},
                    'location_name': {'type': 'string', 'description': '活动地点名称（当不选择场馆时使用）', 'example': '社区篮球场'},
                    'location_address': {'type': 'string', 'description': '活动地点地址', 'example': '北京市朝阳区XX街道XX号'},
                    'start_time': {'type': 'string', 'description': '开始时间（YYYY-MM-DD HH:MM:SS）', 'example': '2025-01-25 14:00:00'},
                    'end_time': {'type': 'string', 'description': '结束时间（YYYY-MM-DD HH:MM:SS）', 'example': '2025-01-25 16:00:00'},
                    'venue_start_time': {'type': 'string', 'description': '场馆预订开始时间（可选，当选择场馆时如不提供则使用活动开始时间）'},
                    'venue_end_time': {'type': 'string', 'description': '场馆预订结束时间（可选，当选择场馆时如不提供则使用活动结束时间）'},
                    'max_participants': {'type': 'integer', 'description': '最大参与人数', 'example': 20, 'minimum': 1, 'maximum': 1000},
                    'min_participants': {'type': 'integer', 'description': '最少参与人数', 'example': 4, 'minimum': 1},
                    'activity_type': {'type': 'string', 'description': '活动类型', 'enum': ['sports', 'social', 'learning', 'other'], 'example': 'sports'},
                    'tags': {'type': 'array', 'items': {'type': 'string'}, 'description': '活动标签', 'example': ['篮球', '运动', '友谊赛']},
                    'is_free': {'type': 'boolean', 'description': '是否免费', 'example': True},
                    'fee': {'type': 'number', 'description': '活动费用（当is_free为false时）', 'example': 50.0},
                    'fee_description': {'type': 'string', 'description': '费用说明', 'example': '包含场地费和饮水费'},
                    'contact_info': {'type': 'string', 'description': '联系方式', 'example': '微信：basketball_lover'},
                    'requirements': {'type': 'string', 'description': '参与要求', 'example': '请自备运动装备，有一定篮球基础'},
                    'notes': {'type': 'string', 'description': '备注信息', 'example': '雨天取消，另行通知'},
                    'images': {'type': 'array', 'items': {'type': 'string'}, 'description': '活动图片URL列表', 'example': ['/uploads/activity/image1.jpg']},
                    'registration_deadline': {'type': 'string', 'description': '报名截止时间（YYYY-MM-DD HH:MM:SS）', 'example': '2025-01-24 20:00:00'},
                    'need_approval': {'type': 'boolean', 'description': '是否需要审核', 'example': False},
                    'allow_waitlist': {'type': 'boolean', 'description': '是否允许候补', 'example': True}
                }
            }
        }
    ],
    'responses': {
        200: {
            'description': '创建成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '活动创建成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'id': {'type': 'integer', 'description': '新创建的活动ID', 'example': 124},
                            'title': {'type': 'string', 'description': '活动标题', 'example': '周末篮球友谊赛'},
                            'organizer_id': {'type': 'integer', 'description': '组织者ID', 'example': 5},
                            'status': {'type': 'string', 'description': '活动状态', 'example': 'open'},
                            'created_at': {'type': 'string', 'description': '创建时间', 'example': '2025-01-20 16:30:00'},
                            'start_time': {'type': 'string', 'description': '开始时间', 'example': '2025-01-25 14:00:00'},
                            'end_time': {'type': 'string', 'description': '结束时间', 'example': '2025-01-25 16:00:00'},
                            'max_participants': {'type': 'integer', 'description': '最大参与人数', 'example': 20},
                            'venue_name': {'type': 'string', 'description': '场馆名称', 'example': '篮球场A'},
                            'location_name': {'type': 'string', 'description': '活动地点', 'example': '社区篮球场'}
                        }
                    }
                }
            }
        },
        400: {
            'description': '参数错误',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 400},
                    'message': {'type': 'string', 'example': '参数错误：标题不能为空'}
                }
            }
        },
        401: {
            'description': 'token验证失败，需要重新登录'
        },
        500: {
            'description': '服务器内部错误'
        }
    }
})
def create_activity():
    """创建活动"""
    try:
        data = request.get_json()
        
        # 验证必要参数
        required_fields = ['title', 'start_time', 'end_time']
        for field in required_fields:
            if not data.get(field):
                return error_response(f'缺少必要参数: {field}', 400)
        
        # 验证场馆是否存在（如果提供了场馆ID）
        venue = None
        venue_id = data.get('venue_id')
        # 如果venue_id为0或空字符串，视为不选择场馆
        if venue_id == 0 or venue_id == '':
            venue_id = None
        if venue_id:
            venue = Venue.query.get(venue_id)
            if not venue:
                return error_response('场馆不存在', 400)
        
        # 解析时间
        try:
            start_time = datetime.strptime(data['start_time'], '%Y-%m-%d %H:%M:%S')
            end_time = datetime.strptime(data['end_time'], '%Y-%m-%d %H:%M:%S')
        except ValueError:
            return error_response('时间格式错误，请使用 YYYY-MM-DD HH:MM:SS 格式', 400)
        
        # 解析场馆预订时间（可选）
        venue_start_time = None
        venue_end_time = None
        
        # 如果选择了场馆，处理场馆使用时间
        if venue_id:
            # 检查是否传入了有效的场馆时间参数（不为空字符串）
            venue_start_time_str = data.get('venue_start_time', '').strip()
            venue_end_time_str = data.get('venue_end_time', '').strip()
            
            if venue_start_time_str or venue_end_time_str:
                # 如果传入了场馆时间参数，则解析并验证
                if venue_start_time_str:
                    try:
                        venue_start_time = datetime.strptime(venue_start_time_str, '%Y-%m-%d %H:%M:%S')
                    except ValueError:
                        return error_response('场馆开始时间格式错误', 400)
                
                if venue_end_time_str:
                    try:
                        venue_end_time = datetime.strptime(venue_end_time_str, '%Y-%m-%d %H:%M:%S')
                    except ValueError:
                        return error_response('场馆结束时间格式错误', 400)
                
                # 验证场馆时间逻辑（只在传入时间参数时验证）
                if venue_start_time and venue_end_time:
                    if venue_start_time >= venue_end_time:
                        return error_response('场馆预订开始时间必须早于结束时间', 400)
                elif venue_start_time and not venue_end_time:
                    return error_response('场馆开始时间和结束时间必须同时提供', 400)
                elif not venue_start_time and venue_end_time:
                    return error_response('场馆开始时间和结束时间必须同时提供', 400)
            else:
                # 如果没有传入场馆时间参数或为空字符串，使用活动时间作为默认值
                venue_start_time = start_time
                venue_end_time = end_time
        
        # 解析报名截止时间（可选）
        registration_deadline = None
        if data.get('registration_deadline'):
            try:
                registration_deadline = datetime.strptime(data['registration_deadline'], '%Y-%m-%d %H:%M:%S')
            except ValueError:
                return error_response('报名截止时间格式错误', 400)
        
        # 验证时间逻辑
        if start_time >= end_time:
            return error_response('开始时间必须早于结束时间', 400)
        
        if start_time <= datetime.now():
            return error_response('开始时间必须晚于当前时间', 400)
        
        # 验证报名截止时间
        if registration_deadline and registration_deadline >= start_time:
            return error_response('报名截止时间必须早于活动开始时间', 400)
        
        # 验证参与人数
        max_participants = data.get('max_participants', 20)
        min_participants = data.get('min_participants', 1)
        
        if max_participants < min_participants:
            return error_response('最大参与人数不能小于最少参与人数', 400)
        
        if max_participants > 1000:
            return error_response('最大参与人数不能超过1000人', 400)
        
        # 验证场馆容量
        if venue and venue.max_capacity:
            if max_participants > venue.max_capacity:
                return error_response(f'最大参与人数不能超过场馆容量（{venue.max_capacity}人）', 400)
        
        # 如果选择了场馆且设置了场馆使用时间，检查时间段冲突
        if venue_id and venue and venue_start_time and venue_end_time:
            conflicting_activities = Activity.query.filter(
                Activity.venue_id == venue_id,
                Activity.status.in_(['open', 'closed']),  # 排除已取消的活动
                Activity.is_active == True,
                db.or_(
                    # 活动开始时间在查询时间段内
                    db.and_(Activity.venue_start_time >= venue_start_time, Activity.venue_start_time < venue_end_time),
                    # 活动结束时间在查询时间段内
                    db.and_(Activity.venue_end_time > venue_start_time, Activity.venue_end_time <= venue_end_time),
                    # 活动时间段包含查询时间段
                    db.and_(Activity.venue_start_time <= venue_start_time, Activity.venue_end_time >= venue_end_time)
                )
            ).first()
            
            if conflicting_activities:
                return error_response(f'场馆在该时间段已被活动"{conflicting_activities.title}"占用', 400)
        
        # 验证费用设置
        is_free = data.get('is_free', True)
        fee = 0
        if not is_free:
            fee = data.get('fee', 0)
            if fee <= 0:
                return error_response('收费活动必须设置费用金额', 400)
        
        # 处理图片
        images = data.get('images', [])
        if not images:
            # 如果没有上传图片，使用默认图片
            images = ['/static/images/default-activity.jpg']
        
        # 处理标签
        tags = data.get('tags', [])
        
        # 验证活动类型
        activity_type = data.get('activity_type', 'other')
        valid_types = ['sports', 'social', 'learning', 'other']
        if activity_type not in valid_types:
            return error_response(f'无效的活动类型，支持的类型：{", ".join(valid_types)}', 400)
        
        # 创建活动
        activity = Activity(
            title=data['title'],
            description=data.get('description', ''),
            organizer_id=g.current_user_id,  # 当前用户作为组织者
            venue_id=venue_id,
            start_time=start_time,
            end_time=end_time,
            venue_start_time=venue_start_time,
            venue_end_time=venue_end_time,
            registration_deadline=registration_deadline,
            max_participants=max_participants,
            min_participants=min_participants,
            activity_type=activity_type,
            tags=json.dumps(tags) if tags else None,
            is_free=is_free,
            fee=fee,
            fee_description=data.get('fee_description', ''),
            contact_info=data.get('contact_info', ''),
            location_name=data.get('location_name', ''),
            location_address=data.get('location_address', ''),
            requirements=data.get('requirements', ''),
            notes=data.get('notes', ''),
            images=json.dumps(images),
            need_approval=data.get('need_approval', False),
            allow_waitlist=data.get('allow_waitlist', True),
            status='open'  # 新创建的活动默认开放
        )
        
        db.session.add(activity)
        db.session.commit()
        
        # 返回创建成功的活动信息
        result_data = {
            'id': activity.id,
            'title': activity.title,
            'organizer_id': activity.organizer_id,
            'status': activity.status,
            'created_at': safe_datetime_format(activity.created_at),
            'start_time': safe_datetime_format(activity.start_time),
            'end_time': safe_datetime_format(activity.end_time),
            'max_participants': activity.max_participants,
            'venue_name': venue.name if venue else None,
            'location_name': activity.location_name
        }
        
        return success_response(result_data, '活动创建成功')
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"创建活动失败: {str(e)}")
        return error_response('创建失败', 500)


@activity_bp.route('/<int:activity_id>/generate_order', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '为活动绑定场地并生成预订订单',
    'description': '''活动发起者为已创建但未绑定场地的活动，通过此接口传入场地信息，将活动与场地绑定并生成待支付订单。\n- 必须是活动的组织者才能调用。\n- 活动必须尚未关联任何场地。\n- 请求体中需要提供`venue_id`, `start_time`, `end_time`（带完整日期时间）。\n- 系统会根据时间中的日期计算星期几，然后查找对应的时间段。\n- 开始时间和结束时间必须在同一天。\n- 成功后，活动信息会被更新，并创建一个关联此活动的订单。''',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '目标活动ID'
        },
        {
            'name': 'body',
            'in': 'body',
            'required': True,
            'schema': {
                'type': 'object',
                'required': ['venue_id', 'start_time', 'end_time'],
                'properties': {
                    'venue_id': {'type': 'integer', 'description': '场馆ID', 'example': 1},
                    'start_time': {'type': 'string', 'description': '开始时间 (YYYY-MM-DD HH:MM:SS)', 'example': '2025-07-07 10:00:00'},
                    'end_time': {'type': 'string', 'description': '结束时间 (YYYY-MM-DD HH:MM:SS)', 'example': '2025-07-07 12:00:00'},
                    'participant_count': {'type': 'integer', 'description': '预订人数', 'default': 1, 'example': 5},
                    'remark': {'type': 'string', 'description': '备注信息（可选）', 'example': '活动场地预定，请准备运动装备'}
                }
            }
        }
    ],
    'responses': {
        200: {
            'description': '订单生成成功，活动已绑定场地',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '订单生成成功'},
                    'data': {
                        'allOf': [
                            {'$ref': '#/definitions/Order'},
                            {
                                'type': 'object',
                                'properties': {
                                    'user_phone': {
                                        'type': 'string',
                                        'description': '订单创建者的手机号',
                                        'example': '13800138000'
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        },
        400: {
            'description': '参数错误、活动已绑定场地或场地信息无效'
        },
        403: {
            'description': '权限不足，非活动发起者'
        },
        404: {
            'description': '活动、场馆或时间段不存在'
        },
        409: {
            'description': '场地时间冲突或活动已有订单'
        }
    }
})
def generate_order_from_activity(activity_id):
    """为活动预订场地并生成订单"""
    
    # 获取当前用户ID
    current_user_id = g.current_user_id
    
    # 从数据库获取当前用户对象
    from app.models.user import User
    current_user = User.query.get(current_user_id)
    if not current_user:
        return error_response('用户不存在', 404)
    
    data = request.get_json()
    if not data:
        return error_response('请求体不能为空', 400)

    venue_id = data.get('venue_id')
    start_time_str = data.get('start_time')
    end_time_str = data.get('end_time')
    participant_count = data.get('participant_count', 1)
    remark = data.get('remark', '活动场地预定')

    if not all([venue_id, start_time_str, end_time_str]):
        return error_response('缺少必要的参数：venue_id, start_time, end_time', 400)

    try:
        start_time = datetime.strptime(start_time_str, '%Y-%m-%d %H:%M:%S')
        end_time = datetime.strptime(end_time_str, '%Y-%m-%d %H:%M:%S')
    except ValueError:
        return error_response('时间格式错误，应为 YYYY-MM-DD HH:MM:SS', 400)

    if start_time.date() != end_time.date():
        return error_response('开始和结束时间必须在同一天', 400)
    
    try:
        activity = Activity.query.get(activity_id)
        if not activity:
            return error_response('活动不存在', 404)

        if activity.organizer_id != int(current_user.id):
            return error_response('权限不足，只有活动发起者才能操作', 403)

        if activity.venue_id:
            return error_response('此活动已关联场地，无法重复操作', 400)
            
        existing_order = Order.query.filter_by(activity_id=activity.id, status=0).first()
        if existing_order:
            return error_response('此活动已有待处理订单，请勿重复生成', 409)

        # 验证场馆
        from app.models.venue import Venue, VenueTimeSlot
        venue = Venue.query.get(venue_id)
        if not venue:
            return error_response('场馆不存在', 404)
        if venue.status != 1:
            return error_response('场馆未开放', 400)

        # 查找对应的时间段
        weekday = start_time.weekday() + 1  # Python的weekday(): 0=Monday, 数据库: 1=Monday
        start_time_str = start_time.strftime('%H:%M')
        end_time_str = end_time.strftime('%H:%M')
        
        # 先尝试完全匹配
        time_slot = VenueTimeSlot.query.filter_by(
            venue_id=venue_id,
            day_of_week=weekday,
            start_time=start_time_str,
            end_time=end_time_str,
            status=1
        ).first()
        
        if not time_slot:
            # 如果找不到完全匹配的时间段，寻找包含这个时间范围的时间段
            time_slot = VenueTimeSlot.query.filter_by(
                venue_id=venue_id,
                day_of_week=weekday,
                status=1
            ).filter(
                VenueTimeSlot.start_time <= start_time_str,
                VenueTimeSlot.end_time >= end_time_str
            ).first()
        
        if not time_slot:
            # 如果还是找不到，就使用该场馆该天的任意一个时间段
            time_slot = VenueTimeSlot.query.filter_by(
                venue_id=venue_id,
                day_of_week=weekday,
                status=1
            ).first()
        
        if not time_slot:
            # 如果该天没有时间段，使用该场馆的任意一个时间段
            time_slot = VenueTimeSlot.query.filter_by(
                venue_id=venue_id,
                status=1
            ).first()
        
        if not time_slot:
            return error_response('该场馆暂无可用时间段', 400)

        # 检查时间冲突
        booking_date = start_time.date()
        conflicting_order = Order.query.filter(
            Order.venue_id == venue_id,
            Order.reservation_date == booking_date,
            Order.status.in_([0, 1, 3])  # 未支付、已支付、已完成
        ).first()
        
        if conflicting_order:
            return error_response('该时间段已被预订', 409)

        # 生成订单号
        import time
        order_no = f"ACT{int(time.time())}"
        
        # 创建订单
        order = Order(
            order_no=order_no,
            user_id=current_user.id,
            venue_id=venue_id,
            activity_id=activity.id,
            time_slot_id=time_slot.id,
            reservation_date=booking_date,
            start_time=start_time_str,
            end_time=end_time_str,
            amount=time_slot.price,
            participant_count=participant_count,
            status=0,  # 未支付
            remark=remark
        )
        
        db.session.add(order)
        
        # 检查活动是否需要设置默认图片
        import json
        current_images = json.loads(activity.images) if activity.images else []
        
        if not current_images:  # 如果活动没有上传图片，根据场馆类型设置默认图片
            default_image = None
            venue_type = venue.type.lower() if venue.type else ""
            
            if "足球" in venue_type or "football" in venue_type or "soccer" in venue_type:
                default_image = "/uploads/activity/106a49c4-1598-4ae5-a018-5b29408ef65e.jpeg"
            elif "篮球" in venue_type or "basketball" in venue_type:
                default_image = "/uploads/activity/1e03ccbc-0427-46ac-99c5-0ea833be3d94.jpg"
            
            if default_image:
                activity.images = json.dumps([default_image])
        
        # 更新活动的场馆信息
        activity.venue_id = venue_id
        activity.venue_start_time = start_time
        activity.venue_end_time = end_time
        
        db.session.commit()

        response_data = {
            'order': order.to_dict(with_activity=True, with_venue=True),
            'user': current_user.to_dict()
        }
        
        return success_response(response_data, '订单生成成功', 200)

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"为活动生成订单失败: {str(e)}")
        if "时间冲突" in str(e):
            return error_response('预订失败，该时间段已被预订', 409)
        return error_response('操作失败，请重试', 500)

@activity_bp.route('/my_unbound', methods=['GET'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '我发起的未绑定场地的活动列表',
    'description': '获取当前用户发起且尚未关联任何场地的活动列表。用于在创建活动后，选择活动以绑定场地。需要在请求头中包含JWT token。返回格式与 /my 接口中 organized_activities 部分保持一致。',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}'
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'organized_activities': {
                                'type': 'object',
                                'description': '我发起的未绑定场地的活动',
                                'properties': {
                                    'total': {'type': 'integer'},
                                    'activities': {
                                        'type': 'array',
                                        'items': {
                                            'type': 'object',
                                            'properties': {
                                                'id': {'type': 'integer'},
                                                'title': {'type': 'string'},
                                                'description': {'type': 'string'},
                                                'start_time': {'type': 'string'},
                                                'end_time': {'type': 'string'},
                                                'status': {'type': 'string'},
                                                'participant_count': {'type': 'integer'},
                                                'max_participants': {'type': 'integer'},
                                                'venue_name': {'type': 'string', 'nullable': True},
                                                'created_at': {'type': 'string'},
                                                'is_free': {'type': 'boolean'},
                                                'fee': {'type': 'number'},
                                                'fee_description': {'type': 'string'}
                                            }
                                        }
                                    }
                                }
                            },
                            'participated_activities': {
                                'type': 'object',
                                'description': '我参与的活动（此处为空）',
                                'properties': {
                                    'total': {'type': 'integer', 'example': 0},
                                    'activities': {'type': 'array', 'example': []}
                                }
                            }
                        }
                    }
                }
            }
        },
        401: {'$ref': '#/responses/UnauthorizedError'}
    }
})
def get_my_unbound_activities():
    """获取我发起的、未绑定场馆的活动列表"""
    try:
        user_id = g.current_user_id
        
        # 查询用户发起、未绑定场地且状态为开放的活动
        unbound_activities = Activity.query.filter_by(
            organizer_id=user_id, 
            venue_id=None, 
            status='open', 
            is_active=True
        ).order_by(Activity.created_at.desc()).all()
        
        activities_data = [
            activity.to_dict(
                include_venue=True, 
                include_organizer=False, # 不需要包含组织者信息，因为就是当前用户
                include_participants=False # 未绑定场地活动通常没有参与者
            ) for activity in unbound_activities
        ]

        # 构造与 /my 接口一致的返回结构
        response_data = {
            'organized_activities': {
                'total': len(activities_data),
                'activities': activities_data
            },
            'participated_activities': {
                'total': 0,
                'pages': 0,
                'page': 0,
                'perPage': 0,
                'activities': []
            }
        }
        
        return success_response(data=response_data)
        
    except Exception as e:
        current_app.logger.error(f"获取未绑定场地的活动失败: {e}", exc_info=True)
        return error_response(500, '服务器内部错误')

@activity_bp.route('/<int:activity_id>/manage_waitlist', methods=['GET'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '活动创建人查看候补名单',
    'description': '活动创建人查看自己活动的候补名单，支持分页查询。只有活动创建人才能查看完整的候补名单信息。',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}'
        },
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '活动ID'
        },
        {
            'name': 'page',
            'in': 'query',
            'type': 'integer',
            'default': 1,
            'description': '页码，从1开始'
        },
        {
            'name': 'per_page',
            'in': 'query',
            'type': 'integer',
            'default': 20,
            'description': '每页显示数量'
        }
    ],
    'responses': {
        200: {
            'description': '获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '获取成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'activity_id': {'type': 'integer'},
                            'activity_title': {'type': 'string'},
                            'current_participants': {'type': 'integer', 'description': '当前参与人数'},
                            'max_participants': {'type': 'integer', 'description': '最大参与人数'},
                            'total_waitlist': {'type': 'integer', 'description': '候补总人数'},
                            'pages': {'type': 'integer', 'description': '总页数'},
                            'page': {'type': 'integer', 'description': '当前页码'},
                            'per_page': {'type': 'integer', 'description': '每页数量'},
                            'waitlist_users': {
                                'type': 'array',
                                'description': '候补用户列表',
                                'items': {
                                    'type': 'object',
                                    'properties': {
                                        'participant_id': {'type': 'integer', 'description': '参与记录ID'},
                                        'user_id': {'type': 'integer', 'description': '用户ID'},
                                        'nickname': {'type': 'string', 'description': '用户昵称'},
                                        'avatar_url': {'type': 'string', 'description': '用户头像'},
                                        'phone': {'type': 'string', 'description': '用户手机号'},
                                        'waitlist_time': {'type': 'string', 'description': '加入候补时间'},
                                        'position': {'type': 'integer', 'description': '候补排队位置'}
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        403: {
            'description': '权限不足，只有活动创建人可以查看'
        },
        404: {
            'description': '活动不存在'
        }
    }
})
def get_activity_waitlist_for_organizer(activity_id):
    """活动创建人查看候补名单"""
    try:
        # 获取当前用户
        current_user_id = g.current_user_id
        
        # 检查活动是否存在
        activity = Activity.query.get(activity_id)
        if not activity:
            return error_response('活动不存在', 404)
        
        # 检查是否为活动创建人
        if activity.organizer_id != current_user_id:
            return error_response('权限不足，只有活动创建人可以查看候补名单', 403)
        
        # 获取分页参数
        page = request.args.get('page', 1, type=int)
        per_page = request.args.get('per_page', 20, type=int)
        
        # 查询候补用户列表
        waitlist_query = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='waitlist'
        ).order_by(ActivityParticipant.created_at.asc())
        
        # 分页
        pagination = waitlist_query.paginate(
            page=page, 
            per_page=per_page, 
            error_out=False
        )
        
        # 构建返回数据
        waitlist_users = []
        for idx, participant in enumerate(pagination.items):
            user = User.query.get(participant.user_id)
            if user:
                waitlist_users.append({
                    'participant_id': participant.id,
                    'user_id': user.id,
                    'nickname': user.nickname or user.phone,
                    'avatar_url': user.avatar_url,
                    'phone': user.phone,
                    'waitlist_time': participant.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                    'position': (page - 1) * per_page + idx + 1
                })
        
        # 获取当前参与人数
        current_participants = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='joined'
        ).count()
        
        # 获取候补总人数
        total_waitlist = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='waitlist'
        ).count()
        
        return success_response('获取成功', {
            'activity_id': activity.id,
            'activity_title': activity.title,
            'current_participants': current_participants,
            'max_participants': activity.max_participants,
            'total_waitlist': total_waitlist,
            'pages': pagination.pages,
            'page': page,
            'per_page': per_page,
            'waitlist_users': waitlist_users
        })
        
    except Exception as e:
        print(f"获取候补名单失败: {str(e)}")
        return error_response('获取候补名单失败', 500)


@activity_bp.route('/<int:activity_id>/approve_waitlist/<int:participant_id>', methods=['POST'])
@login_required
@swag_from({
    'tags': ['用户-活动'],
    'summary': '活动创建人同意候补用户参与',
    'description': '活动创建人同意候补名单中的用户参与活动。候补用户被同意后可以超过原来的最大参与人数限制，给活动创建人更大的灵活性。只有活动创建人才能执行此操作。',
    'security': [{'Bearer': []}],
    'parameters': [
        {
            'name': 'Authorization',
            'in': 'header',
            'required': True,
            'type': 'string',
            'description': 'JWT token，格式：Bearer {token}'
        },
        {
            'name': 'activity_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '活动ID'
        },
        {
            'name': 'participant_id',
            'in': 'path',
            'type': 'integer',
            'required': True,
            'description': '参与者记录ID（候补用户的参与记录ID）'
        }
    ],
    'responses': {
        200: {
            'description': '同意成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'code': {'type': 'integer', 'example': 200},
                    'message': {'type': 'string', 'example': '同意候补成功'},
                    'data': {
                        'type': 'object',
                        'properties': {
                            'activity_id': {'type': 'integer'},
                            'participant_id': {'type': 'integer'},
                            'user': {
                                'type': 'object',
                                'properties': {
                                    'id': {'type': 'integer'},
                                    'nickname': {'type': 'string'},
                                    'phone': {'type': 'string'},
                                    'avatar_url': {'type': 'string'}
                                }
                            },
                            'previous_status': {'type': 'string', 'example': 'waitlist'},
                            'new_status': {'type': 'string', 'example': 'joined'},
                            'previous_waitlist_position': {'type': 'integer'},
                            'approved_at': {'type': 'string'},
                            'current_participants': {'type': 'integer', 'description': '当前参与人数（包括刚同意的用户）'},
                            'max_participants': {'type': 'integer', 'description': '原最大参与人数'},
                            'is_over_limit': {'type': 'boolean', 'description': '是否超过原定人数限制'}
                        }
                    }
                }
            }
        },
        400: {
            'description': '参数错误或用户不在候补名单中'
        },
        403: {
            'description': '权限不足，只有活动创建人可以操作'
        },
        404: {
            'description': '活动不存在或参与记录不存在'
        }
    }
})
def approve_waitlist_user(activity_id, participant_id):
    """活动创建人同意候补用户参与"""
    try:
        # 获取当前用户
        current_user_id = g.current_user_id
        
        # 检查活动是否存在
        activity = Activity.query.get(activity_id)
        if not activity:
            return error_response('活动不存在', 404)
        
        # 检查是否为活动创建人
        if activity.organizer_id != current_user_id:
            return error_response('权限不足，只有活动创建人可以同意候补用户', 403)
        
        # 检查参与记录是否存在
        participant = ActivityParticipant.query.get(participant_id)
        if not participant:
            return error_response('参与记录不存在', 404)
        
        # 检查参与记录是否属于该活动
        if participant.activity_id != activity_id:
            return error_response('参与记录与活动不匹配', 400)
        
        # 检查用户是否在候补状态
        if participant.status != 'waitlist':
            return error_response('用户不在候补名单中', 400)
        
        # 获取用户信息
        user = User.query.get(participant.user_id)
        if not user:
            return error_response('用户不存在', 404)
        
        # 计算之前的候补位置
        previous_waitlist_position = ActivityParticipant.query.filter(
            ActivityParticipant.activity_id == activity_id,
            ActivityParticipant.status == 'waitlist',
            ActivityParticipant.created_at < participant.created_at
        ).count() + 1
        
        # 获取当前参与人数
        current_participants = ActivityParticipant.query.filter_by(
            activity_id=activity_id,
            status='joined'
        ).count()
        
        # 更新参与状态
        participant.status = 'joined'
        participant.updated_at = datetime.utcnow()
        
        # 更新活动参与人数
        activity.participant_count = current_participants + 1
        
        # 提交数据库更改
        db.session.commit()
        
        # 判断是否超过原定人数限制
        is_over_limit = activity.participant_count > activity.max_participants
        
        return success_response('同意候补成功', {
            'activity_id': activity.id,
            'participant_id': participant.id,
            'user': {
                'id': user.id,
                'nickname': user.nickname or user.phone,
                'phone': user.phone,
                'avatar_url': user.avatar_url
            },
            'previous_status': 'waitlist',
            'new_status': 'joined',
            'previous_waitlist_position': previous_waitlist_position,
            'approved_at': participant.updated_at.strftime('%Y-%m-%d %H:%M:%S'),
            'current_participants': activity.participant_count,
            'max_participants': activity.max_participants,
            'is_over_limit': is_over_limit
        })
        
    except Exception as e:
        db.session.rollback()
        print(f"同意候补用户失败: {str(e)}")
        return error_response('同意候补用户失败', 500)
